﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace r4u.data.access.layer.REGISTER
{
    public class UserDAO
    {

        public CUSTOMER_ACCOUNT GetUser(string email)
        {
            using (var context = new r4uEntities())
            {
                CUSTOMER_ACCOUNT account = context.CUSTOMER_ACCOUNT.Include("VACANCies").FirstOrDefault(
                             user => user.email.Equals(email));

                return account;
            }
        }


        public string GetEmailBySecurityCode(string code)
        {
            using (var context = new r4uEntities())
            {
                try
                {
                    code = this.Encrypt(code);

                    CUSTOMER_ACCOUNT account = context.CUSTOMER_ACCOUNT.FirstOrDefault(
                        user => user.activation_code.Equals(code));
                    return account.email;
                }
                catch (Exception e)
                {
                    return string.Empty;
                }
            }
        }


        public bool ActivateAccount(string email, DateTime start, DateTime end, string status)
        {
            using (var context = new r4uEntities())
            {
                try
                {
                    CUSTOMER_ACCOUNT account = context.CUSTOMER_ACCOUNT.FirstOrDefault(
                             user => user.email.Equals(email));

                    account.activated = start;
                    account.expired = end;
                    account.status = status;

                    context.SaveChanges();
                    return true;
                }
                catch (Exception)
                {
                    return false;
                }
            }
        }


        public bool ResetPassword(string email, string password)
        {
            using (var context = new r4uEntities())
            {
                try
                {
                    CUSTOMER_ACCOUNT account = context.CUSTOMER_ACCOUNT.FirstOrDefault(
                             user => user.email.Equals(email));

                    account.password = this.Encrypt(password);

                    context.SaveChanges();
                    return true;
                }
                catch (Exception)
                {
                    return false;
                }
            }
        }

        public bool UpdateStatus(string email, string status)
        {
            using (var context = new r4uEntities())
            {
                try
                {
                    CUSTOMER_ACCOUNT account = context.CUSTOMER_ACCOUNT.FirstOrDefault(
                             user => user.email.Equals(email));
                    account.status = status;
                    context.SaveChanges();
                    return true;
                }
                catch (Exception)
                {
                    return false;
                }
            }
        }

        public bool CheckActivationCode(string email, string code)
        {
            return this.GetCode(email).Equals(code);
        }

        public string GetCode(string email)
        {
            using (var context = new r4uEntities())
            {
                return this.Decrypt(context.CUSTOMER_ACCOUNT.FirstOrDefault(
                    user => user.email.Equals(email)).activation_code);
            }
        }


        public string GetStatus(string email)
        {
            using (var context = new r4uEntities())
            {
                return context.CUSTOMER_ACCOUNT.FirstOrDefault(user => user.email.Equals(email)).status.ToString();
            }
        }


        public string GetPhone(string email)
        {
            using (var context = new r4uEntities())
            {
                return context.CUSTOMER_ACCOUNT.FirstOrDefault(user => user.email.Equals(email)).phone.ToString();
            }
        }


        public bool CheckUser(string email, string password)
        {
            password = this.Encrypt(password);

            using (var context = new r4uEntities())
            {
                return context.CUSTOMER_ACCOUNT.Any(user => user.email.Equals(email) && user.password.Equals(password));
            } 
        }

        public bool CheckExist(string email)
        {
            using (var context = new r4uEntities())
            {
                return context.CUSTOMER_ACCOUNT.Any(user => user.email.Equals(email));
            }
        }

        private int GetNextCustId___()
        {
            using (var context = new r4uEntities())
            {
                return 1000 + context.CUSTOMER_ACCOUNT.Count();
            }
        }

        public bool InsertUser(string name, string company_name, string address1, string address2,
            string zip_code, string city, string state, string country, string email,
            Nullable<int> phone, string receive_mail, string receive_sms, string password)
        {
            try
            {
                CUSTOMER_ACCOUNT account = new CUSTOMER_ACCOUNT();
                account.customer_id = this.GetNextCustId___().ToString();
                account.name = name;
                account.company_name = company_name;
                account.address1 = address1;
                account.address2 = address2;
                account.zip_code = zip_code;
                account.city = city;
                account.state = state;
                account.country = country;
                account.email = email;
                account.phone = phone;
                account.receive_mail = receive_mail;
                account.receive_sms = receive_sms;
                account.password = this.Encrypt(password);
                account.status = "CREATED";
                account.activation_code = this.Encrypt(this.GenerateNewCode(6));

                using (var context = new r4uEntities())
                {
                    context.CUSTOMER_ACCOUNT.Add(account);
                    context.SaveChanges();
                }

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        private string Encrypt(string clearText)
        {
            string EncryptionKey = "MAKV2SPBNI99212";
            byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
            using (Aes encryptor = Aes.Create())
            {
                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                encryptor.Key = pdb.GetBytes(32);
                encryptor.IV = pdb.GetBytes(16);
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(clearBytes, 0, clearBytes.Length);
                        cs.Close();
                    }
                    clearText = Convert.ToBase64String(ms.ToArray());
                }
            }
            return clearText;
        }

        private string Decrypt(string cipherText)
        {
            string EncryptionKey = "MAKV2SPBNI99212";
            byte[] cipherBytes = Convert.FromBase64String(cipherText);
            using (Aes encryptor = Aes.Create())
            {
                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                encryptor.Key = pdb.GetBytes(32);
                encryptor.IV = pdb.GetBytes(16);
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(cipherBytes, 0, cipherBytes.Length);
                        cs.Close();
                    }
                    cipherText = Encoding.Unicode.GetString(ms.ToArray());
                }
            }
            return cipherText;
        }

        public string GenerateNewCode(int CodeLength)
        {
            Random random = new Random();

            StringBuilder output = new StringBuilder();

            for (int i = 0; i < CodeLength; i++)
            {
                output.Append(random.Next(1, 9));
            }

            return output.ToString();
        }


        public string GetCustIdByEmail(string email)
        {
            using (var context = new r4uEntities())
            {
                try
                {
                    CUSTOMER_ACCOUNT account = context.CUSTOMER_ACCOUNT.FirstOrDefault(
                        user => user.email.Equals(email));
                    return account.customer_id;
                }
                catch (Exception e)
                {
                    return string.Empty;
                }
            }
        }
    }
}
